package com.gitee.ywj1352.client.factory.impl;

import com.gitee.ywj1352.client.ClientParser;
import com.gitee.ywj1352.common.util.ClientStructure;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 
 * @author wenjieyang
 */
public class DefaultClientParser implements ClientParser {

    private ConcurrentHashMap<Class<?>, ClientStructure> clientClazzCache = new ConcurrentHashMap<>();

    @Override
    public <T> ClientStructure parse(Class<T> clientClazz) {
        if (!checkInterface(clientClazz)) {
            throw new RuntimeException("it not interface");
        }
        if (clientClazzCache.containsKey(clientClazz)) {
            return clientClazzCache.get(clientClazz);
        }
        Method[] declaredMethods = clientClazz.getDeclaredMethods();
        Map<String, ClientStructure.MethodStructure> map = Stream.of(declaredMethods).map(m -> {
            ClientStructure.MethodStructure methodStructure = new ClientStructure.MethodStructure();
            methodStructure.setMethod(m);
            methodStructure.setName(m.getName());
            Class<?>[] parameterTypes = m.getParameterTypes();
            methodStructure.setParamsType(parameterTypes);
            methodStructure.setReturnClazz(m.getReturnType());
            return methodStructure;
        }).collect(Collectors.toMap(ClientStructure.MethodStructure::getName, c -> c));
        ClientStructure clientStructure = new ClientStructure();
        clientStructure.setClientClazz(clientClazz);
        clientStructure.setMethodsMap(map);
        clientClazzCache.put(clientClazz, clientStructure);
        return clientStructure;
    }

    private <T> boolean checkInterface(Class<T> clientClazz) {
        return clientClazz.isInterface();
    }
}
